home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
Add-ons
/
VideoShop Plug-In Kit 1.0
/
SampleFilt.p
< prev
next >
Wrap
Text File
|
1992-05-06
|
15KB
|
582 lines
{
SampleFilt.p
Sample Filter Effect for DiVA VideoShop
04/28/92 Iván Cavero Belaúnde
}
UNIT SampleFilter;
INTERFACE
USES
Types,Memory,Resources,QuickDraw,QDOffscreen,Dialogs,OSUtils,Packages,Errors,
ToolUtils,SysEqu,GestaltEqu,DiVAFilter;
FUNCTION FilterEntryPoint(selector: INTEGER; params: FiltParamPtr; VAR data: LONGINT;
currentStep, totalSteps: INTEGER): FiltErr;
FUNCTION DoParameters(params: FiltParamPtr): FiltErr;
FUNCTION DoProcessFrame(params: FiltParamPtr; currentStep, totalSteps: INTEGER):
FiltErr;
PROCEDURE DoFilter(src: PixMapHandle; destGW: GWorldPtr; current,total,intensity:
INTEGER);
IMPLEMENTATION
CONST
{ Shades of gray for 3D objects }
kLightGray = $ffff;
kMediumGray = $dddd;
kDarkGray = $aaaa;
{ Dialog item constants }
dialogID = 16001;
defaultItem = 3;
intensityItem = 5;
dividerLinesItem = 7;
imageItem = 9;
frameItem = 10;
forwardItem = 11;
backwardItem = 12;
TYPE
ParamsRecord = RECORD
filterIntensity: INTEGER;
backward: BOOLEAN;
filterParamBlock: FiltParamPtr; { Paramblk for use of custom ditems }
END;
ParamsPtr = ^ParamsRecord;
ParamsHandle = ^ParamsPtr;
RGBColorPtr = ^RGBColor;
FUNCTION FilterEntryPoint(selector: INTEGER; params: FiltParamPtr; VAR data: LONGINT;
currentStep, totalSteps: INTEGER): FiltErr;
BEGIN
CASE selector OF
FiltParameters:
FilterEntryPoint := DoParameters (params);
FiltPrepare:
FilterEntryPoint := noErr;
FiltStart:
FilterEntryPoint := noErr;
FiltProcessFrame:
FilterEntryPoint := DoProcessFrame(params,currentStep,totalSteps);
FiltFinish:
FilterEntryPoint := noErr;
OTHERWISE
FilterEntryPoint := -1;
END;
END;
FUNCTION DoTestAbort(codeAddress: ProcPtr): BOOLEAN;
{ Inline code to call the TestAbort function }
INLINE $205F, { move.l (a7)+,a0 pop procPtr from stack }
$4E90; { jsr (a0) and call it }
FUNCTION TestAbort (params: FiltParamPtr): BOOLEAN;
BEGIN
TestAbort := DoTestAbort(params^.abortProc);
END;
PROCEDURE DoUpdateProgress(done, total: LONGINT; codeAddress: ProcPtr);
{ Inline code to call the UpdateProgress function }
INLINE $205F, { move.l (a7)+,a0 pop procPtr from stack }
$4E90; { jsr (a0) and call it }
PROCEDURE UpdateProgress(params: FiltParamPtr; done, total: LONGINT);
BEGIN
DoUpdateProgress(done,total,params^.progressProc);
END;
PROCEDURE CenterDialogBestDevice(dt: DialogTHndl);
{
Given a dialog template in dt, modify it so as to center the dialog on the
best (deepest) device. Used to place options dialog (with image preview)
in that device.
}
VAR
width, height: INTEGER;
maxDevice: GDHandle;
grayRgn: RgnHandle;
r,dr: Rect;
BEGIN
grayRgn := GetGrayRgn;
r := grayRgn^^.rgnBBox;
maxDevice := GetMaxDevice(r);
r := maxDevice^^.gdRect;
width := r.right - r.left;
height := r.bottom - r.top;
dr := dt^^.boundsRect;
OffsetRect (dr, r.left-dr.left, r.top-dr.top);
OffsetRect (dr, (width - (dr.right-dr.left)) DIV 2,
(height - (dr.bottom-dr.top) - GetMBarHeight) DIV 3 + GetMBarHeight);
dt^^.boundsRect := dr;
END;
FUNCTION GetWindowGDevice(w: WindowPtr): GDHandle;
{
Find the deepest gdevice the window intersects. Used for determining the depth
of the screen we're drawing on (to look good on B/W displays).
}
VAR
r: Rect;
oldPort: GrafPtr;
BEGIN
GetPort(oldPort);
SetPort(w);
r := w^.portRect;
LocalToGlobal(r.topLeft);
LocalToGlobal(r.botRight);
GetWindowGDevice := GetMaxDevice(r);
SetPort (oldPort);
END;
PROCEDURE DrawLines(theDialog: DialogPtr; itemNo: INTEGER);
{
userItem drawing routine for dividing lines (with shadow)
}
VAR
oldColor, greyColor: RGBColor;
itemType: INTEGER;
me: Handle;
box: Rect;
BEGIN
GetDItem(theDialog,itemNo,itemType,me,box);
GetForeColor(oldColor);
RGBForeColor(RGBColorPtr(RGBBlack)^);
MoveTo(box.left,box.top);
LineTo(box.right-2,box.top);
MoveTo(box.left,box.top+3);
LineTo(box.right-2,box.top+3);
IF (GetWindowGDevice(theDialog)^^.gdPMap^^.pixelSize >= 8) THEN
BEGIN
greyColor.red := $7777;
greyColor.green := $7777;
greyColor.blue := $7777;
RGBForeColor (greyColor);
MoveTo(box.left+1, box.top+1);
LineTo(box.right-1, box.top+1);
MoveTo(box.left+1, box.top+4);
LineTo(box.right-1, box.top+4);
END;
RGBForeColor(oldColor);
END;
PROCEDURE OutlineOK(dp: DialogPtr; item: INTEGER);
{
userItem drawing routine for outlining the default button in the dialog box
}
VAR
r: Rect;
h: Handle;
itemType: INTEGER;
BEGIN
item := ok;
GetDItem (dp, item, itemType, h, r);
PenNormal;
PenSize (3, 3);
InsetRect (r, -4, -4);
FrameRoundRect (r, 16, 16);
PenNormal;
END;
PROCEDURE DrawSunkFrame(dp: DialogPtr; item: INTEGER);
{
User item drawing routine for drawing the 3-D-like frame for the preview image.
}
VAR
r: Rect;
h: Handle;
itemType: INTEGER;
oldForeColor, darkGray, lightGray: RGBColor;
bwMode: Boolean;
BEGIN
bwMode := (GetWindowGDevice(dp)^^.gdPMap^^.pixelSize < 8);
GetDItem (dp, item, itemType, h, r);
darkGray.red := kDarkGray;
darkGray.green := kDarkGray;
darkGray.blue := kDarkGray;
lightGray.red := kLightGray;
lightGray.green := kLightGray;
lightGray.blue := kLightGray;
GetForeColor(oldForeColor);
if (NOT bwMode) THEN
BEGIN
RGBForeColor(darkGray);
MoveTo(r.left,r.bottom-1);
LineTo(r.left,r.top);
LineTo(r.right-1,r.top);
END
ELSE RGBForeColor(RGBColorPtr(RGBBlack)^);
MoveTo(r.left+1,r.bottom-2);
LineTo(r.left+1,r.top+1);
LineTo(r.right-2,r.top+1);
IF (NOT bwMode) THEN
BEGIN
RGBForeColor(lightGray);
MoveTo(r.right-1,r.top+1);
LineTo(r.right-1,r.bottom-1);
LineTo(r.left,r.bottom-1);
END
ELSE RGBForeColor(RGBColorPtr(RGBBlack)^);
MoveTo(r.right-2,r.top+2);
LineTo(r.right-2,r.bottom-2);
LineTo(r.left+1,r.bottom-2);
InsetRect(r,2,2);
RGBForeColor(RGBColorPtr(RGBBlack)^);
FrameRect(r);
RGBForeColor(oldForeColor);
END;
PROCEDURE RectLocalToGlobal (VAR r:Rect);
BEGIN
LocalToGlobal(r.topLeft);
LocalToGlobal(r.botRight);
END;
PROCEDURE DrawFilteredImage (dp: DialogPtr; item: INTEGER);
{
User item drawing routine to draw the preview image
}
VAR
r: Rect;
h: Handle;
itemType: INTEGER;
oldGD, destGD: GDHandle;
theParams: ParamsHandle;
params: FiltParamPtr;
oldState: SignedByte;
filtered: PixMapHandle;
oldFore,oldBack: RGBColor;
BEGIN
destGD := GetWindowGDevice(dp);
theParams := ParamsHandle(GetWRefCon(dp));
params := theParams^^.filterParamBlock;
IF (IntegerPtr(SysVersion)^<$700) THEN
filtered := params^.destImage^.portPixMap
ELSE
filtered := GetGWorldPixMap (params^.destImage);
GetDItem (dp, item, itemType, h, r);
oldGD := GetGDevice;
SetGDevice (destGD);
GetForeColor (oldFore);
GetBackColor (oldBack);
RGBForeColor (RGBColorPtr(RGBBlack)^);
RGBBackColor (RGBColorPtr(RGBWhite)^);
oldState := HGetState (Handle(CGrafPtr(dp)^.portPixMap));
HLock (Handle(CGrafPtr(dp)^.portPixMap));
CopyBits(BitMapHandle(filtered)^^,dp^.portBits,filtered^^.bounds,r,srcCopy,nil);
HSetState (Handle(CGrafPtr(dp)^.portPixMap),oldState);
RGBForeColor (oldFore);
RGBBackColor (oldBack);
SetGDevice (oldGD);
END;
PROCEDURE UpdateImage (ctrl: ControlHandle; VAR value: INTEGER);
{
Callback routine for the control to update the preview image. Gets called by
VideoShop's slider control definition while the control is being dragged.
}
VAR
dp: DialogPtr;
theParams: ParamsHandle;
params: FiltParamPtr;
src: PixMapHandle;
oldPort: GrafPtr;
BEGIN
dp := ctrl^^.contrlOwner;
theParams := ParamsHandle(GetWRefCon(dp));
{ Get the parameters handle from the window's refcon }
params := theParams^^.filterParamBlock;
{ Get the parameter block we stuffed there }
src := params^.srcImage;
theParams^^.filterIntensity := value;
DoFilter (src, params^.destImage, 100, 100, theParams^^.filterIntensity);
GetPort (oldPort);
SetPort (dp);
DrawFilteredImage (dp,imageItem);
SetPort (oldPort);
END;
PROCEDURE SetupDItems (dp: DialogPtr);
VAR
itemType: INTEGER;
h: Handle;
r: Rect;
BEGIN
{ Point default useritem to default button outline routine }
GetDItem (dp, defaultItem, itemType, h , r);
SetDItem (dp, defaultItem, itemType, Handle(@OutlineOK), r);
{ Point divider lines useritem to dividing lines drawing routine }
GetDItem (dp, dividerLinesItem, itemType, h , r);
SetDItem (dp, dividerLinesItem, itemType, Handle(@DrawLines), r);
{ Point preview image item to image blitting routine }
GetDItem (dp, imageItem, itemType, h , r);
SetDItem (dp, imageItem, itemType, Handle(@DrawFilteredImage), r);
{ Point preview image frame item to drawing routine }
GetDItem (dp, frameItem, itemType, h , r);
SetDItem (dp, frameItem, itemType, Handle(@DrawSunkFrame), r);
{ Point control's refCon to the the dragging callback routine }
GetDItem (dp, intensityItem, itemType, h, r);
SetCRefCon(ControlHandle(h),LONGINT(@UpdateImage));
END;
PROCEDURE RecalcDItems (p: ParamsHandle; dp: DialogPtr);
VAR
itemType: INTEGER;
fwd, back: ControlHandle;
r: Rect;
BEGIN
GetDItem (dp, intensityItem, itemType, Handle(fwd), r);
p^^.filterIntensity := GetCtlValue(fwd);
GetDItem (dp, forwardItem, itemType, Handle(fwd), r);
GetDItem (dp, backwardItem, itemType, Handle(back), r);
IF (p^^.backward) THEN BEGIN
SetCtlValue(fwd,0);
SetCtlValue(back,1);
END
ELSE BEGIN
SetCtlValue(fwd,1);
SetCtlValue(back,0);
END;
END;
FUNCTION DoParameters (params: FiltParamPtr): FiltErr;
{
Prompt the user for parameters if necessary.
}
VAR
dp: DialogPtr;
dt: DialogTHndl;
theParams: ParamsHandle;
item: INTEGER;
oldPort: GrafPtr;
pmStateSrc,pmStateDest: GWorldFlags;
stateSrc,stateDest: SignedByte;
src,dest: PixMapHandle;
dummy: BOOLEAN;
BEGIN
{ If we didn't get passed a params handle, allocate and initialize it }
IF (params^.parameters = NIL) THEN BEGIN
theParams := ParamsHandle(NewHandleClear(sizeof(ParamsRecord)));
IF (theParams = NIL) THEN BEGIN
DoParameters := FiltErrOutOfMemory + MemError;
Exit(DoParameters);
END;
theParams^^.filterIntensity := 80;
END
ELSE BEGIN
{
Otherwise, we just return. If we required specific hardware or mounds of
memory we would check here.
}
DoParameters := noErr;
Exit(DoParameters);
END;
src := params^.srcImage;
{ Prepare for previewing filter }
{ Get the image pixmaps, dealing with pre-System 7 GetGWorldPixMap bug }
IF (IntegerPtr(SysVersion)^ < $700) THEN
dest := params^.destImage^.portPixMap
ELSE
dest := GetGWorldPixMap (params^.destImage);
{ Save pixmaps' state and lock the buffers }
pmStateSrc := GetPixelsState(src);
dummy := LockPixels (src);
stateSrc := HGetState (Handle(src));
MoveHHi (Handle(src));
HLock (Handle(src));
pmStateDest := GetPixelsState(dest);
dummy := LockPixels (dest);
stateDest := HGetState (Handle(dest));
MoveHHi (Handle(dest));
HLock (Handle(dest));
theParams^^.filterParamBlock := params;
{ Load in the dialog and reposition it in the best device }
dt := DialogTHndl(GetResource ('DLOG', dialogID));
HNoPurge (Handle(dt));
CenterDialogBestDevice (dt);
{ Show it }
dp := GetNewDialog (dialogID, nil, WindowPtr(-1));
GetPort (oldPort);
SetPort (dp);
{ Save our params handle in the window refcon for the user items }
SetWRefCon(dp,LONGINT(theParams));
{ Setup the user items and initialize all controls to initial state }
SetupDItems(dp);
RecalcDItems(theParams,dp);
DoFilter (src, params^.destImage, 100, 100, theParams^^.filterIntensity);
REPEAT
ModalDialog (nil, item);
CASE item OF
forwardItem:
BEGIN
theParams^^.backward := false;
RecalcDItems(theParams,dp);
END;
backwardItem:
BEGIN
theParams^^.backward := true;
RecalcDItems(theParams,dp);
END;
END;
UNTIL ((item = ok) OR (item = cancel));
SetPort (oldPort);
DisposDialog (dp);
HPurge (Handle(dt));
{ Restore pixel maps state }
HSetState (Handle(src),stateSrc);
SetPixelsState(src,pmStateSrc);
HSetState (Handle(dest),stateDest);
SetPixelsState(dest,pmStateDest);
IF (item = cancel) THEN BEGIN
DisposHandle(Handle(theParams));
params^.parameters := nil;
DoParameters := FiltErrReported;
Exit (DoParameters);
END;
params^.parameters := Handle(theParams);
DoParameters := noErr;
END;
PROCEDURE DoFilter (src: PixMapHandle; destGW: GWorldPtr; current,total,
intensity: INTEGER);
{ Perform the filtering operation }
VAR
r,newRect: Rect;
oldFore,oldBack: RGBColor;
oldGW: GWorldPtr;
dest: PixMapHandle;
oldGD: GDHandle;
BEGIN
r := src^^.bounds;
{ Check for pre-System 7 QD bug (GetGWorldPixMap didn't work) }
IF (IntegerPtr(SysVersion)^ < $700) THEN
dest := destGW^.portPixMap
ELSE
dest := GetGWorldPixMap (destGW);
{ Save state }
GetGWorld (oldGW,oldGD);
SetGWorld (destGW,GetGWorldDevice(destGW));
GetForeColor (oldFore);
GetBackColor (oldBack);
RGBForeColor (RGBColorPtr(RGBBlack)^);
RGBBackColor (RGBColorPtr(RGBWhite)^);
{ perform filter }
CopyBits(BitMapHandle(src)^^,BitMapHandle(dest)^^,r,r,srcCopy,nil);
{ Wait for accelerators }
WHILE (NOT (QDDone(GrafPtr(destGW)))) DO;
{ Restore state }
RGBForeColor (oldFore);
RGBBackColor (oldBack);
SetGWorld(oldGW,oldGD);
END;
FUNCTION DoProcessFrame (params: FiltParamPtr; currentStep, totalSteps:
INTEGER) : FiltErr;
VAR
pmStateSrc,pmStateDest: GWorldFlags;
destGW: GWorldPtr;
src,dest: PixMapHandle;
stateSrc,stateDest: SignedByte;
p: ParamsHandle;
dummy: BOOLEAN;
BEGIN
p := ParamsHandle(params^.parameters);
IF (TestAbort (params)) THEN BEGIN
DoProcessFrame := FiltErrReported;
Exit (DoProcessFrame);
END;
src := params^.srcImage;
destGW := params^.destImage;
{ Check for pre-System 7 QD bug (GetGWorldPixMap didn't work) }
IF (IntegerPtr(SysVersion)^ < $700) THEN
dest := destGW^.portPixMap
ELSE
dest := GetGWorldPixMap (destGW);
{ Spin the beachball }
UpdateProgress(params,0,2);
{ save offscreen pixels state and lock them down for drawing }
pmStateSrc := GetPixelsState(src);
dummy := LockPixels (src);
stateSrc := HGetState (Handle(src));
MoveHHi (Handle(src));
HLock (Handle(src));
pmStateDest := GetPixelsState(dest);
dummy := LockPixels (dest);
stateDest := HGetState (Handle(dest));
MoveHHi (Handle(dest));
HLock (Handle(dest));
{ perform filter }
IF (p^^.backward) THEN
DoFilter (src,destGW,totalSteps-currentStep,totalSteps,p^^.filterIntensity)
ELSE
DoFilter (src,destGW,currentStep,totalSteps,p^^.filterIntensity);
UpdateProgress (params,2,2);
HSetState (Handle(src),stateSrc);
SetPixelsState(src,pmStateSrc);
HSetState (Handle(dest),stateDest);
SetPixelsState(dest,pmStateDest);
DoProcessFrame := noErr;
END;
END.